package com.rq.rvlibrary;

import android.content.Context;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.Map;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.recyclerview.widget.RecyclerView;


/**
 * Created by raoqian on 2018/9/21.
 * <p>
 * {@link ViewDataGetter}
 */
public class BaseViewHolder<DATA> extends RecyclerView.ViewHolder {
    public static final int TAG_POSITION = Integer.MAX_VALUE - 10;
    public ActionPasser mActionPasser;
    private SparseArray<View> itemViews = new SparseArray<>();
    SparseArray<TextView> textView = new SparseArray();
    private Context mContext;
    private DATA mData;
    private Object mObject;

    public BaseViewHolder(View itemView) {
        super(itemView);
        if (BaseViewHolder.this instanceof OnInterceptClick) {
            try {
                Method method = get(OnInterceptClick.class).getClass().getMethod("intercept", Object.class, View.class, int.class);
                Annotation[] annotations = method.getAnnotations();
                if (annotations.length > 0) {
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof OnItemClick) {
                            OnItemClick inject = (OnItemClick) annotation;
                            int[] ids = inject.value();
                            for (int id : ids) {
                                if (id == 0) {
                                    itemView.setOnClickListener(itemClick);
                                } else if (itemView.findViewById(id) != null) {
                                    itemView.findViewById(id).setOnClickListener(itemClick);
                                }
                            }
                        }
                    }
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    public <T> T get(Class<T> type) {
        return type.cast(this);
    }

    /**
     * 为了保证代码的后期维护,可以根据定位ViewHolder直接找到布局文件进行修改
     */
    public int inflateLayoutId() {
        return 0;
    }

    /**
     * @return 根视图最终使用 布局文件 ，部分情况 layoutId() ！= inflateLayoutId()
     */
    public final int layoutId() {
        return (int) itemView.getTag(R.id.rv_child_layout);
    }

    public void setData(DATA dataItem) {
        this.mData = dataItem;
    }

    /**
     * @param adapter
     * @param position 头部视图(HeadView)是 position小于 0,3条数据 >> -3,-2,-1
     * @param data
     */
    public void fillData(BaseAdapter adapter, int position, DATA data) {
        // 所有Item 数据为同类 当 有头不视图是 position可能小于 0
    }

    protected final int getPositionInSameClass(int position) {
        if (position >= 0) {
            return position;
        } else {
            return isFootPosition(position) ? position - Integer.MIN_VALUE : ((BaseAdapter) getBindingAdapter())
                    .getHeadSize() + position;
        }
    }

    /**
     * @param position
     * @return 是否头部试图
     * {@link BaseAdapter#addHeadHolder(Object, Class, int, Object)}
     */
    protected final boolean isHeadView(int position) {
        return position < 0 && position > Integer.MIN_VALUE / 2;
    }

    protected final boolean isFootView(int position) {
        return position < Integer.MIN_VALUE / 2;
    }

    protected Object getData() {
        return mData == null ? mObject : mData;
    }

    //特殊场景使用  如瀑布流  params.setFullSpan(true);//占满全屏

    //特殊场景使用  如瀑布流  params.setFullSpan(true);//占满全屏
    public ViewGroup.LayoutParams getLMLayoutParams(@NonNull ViewGroup.LayoutParams oldLM, int measuredWidth, int measuredHeight) {
        return getLMLayoutParams(oldLM);
    }

    @Deprecated
    public ViewGroup.LayoutParams getLMLayoutParams(@NonNull ViewGroup.LayoutParams oldLM) {
        return oldLM;
    }

    public Map<Integer, ViewGroup.LayoutParams> getChildLayoutParams(Map<Integer, ViewGroup.LayoutParams> map, int measuredWidth, int measuredHeight) {
        return getChildLayoutParams(map);
    }

    @Deprecated
    public Map<Integer, ViewGroup.LayoutParams> getChildLayoutParams(Map<Integer, ViewGroup.LayoutParams> map) {
        return map;
    }

    public <T extends View> T getItemView(int id) {
        if (itemViews.get(id) != null) {
            return (T) itemViews.get(id);
        } else {
            T view = itemView.findViewById(id);
            itemViews.put(id, view);
            return view;
        }
    }


    @UiThread
    public BaseViewHolder hideViews(@IdRes int... textViewId) {
        if (textViewId != null && textViewId.length > 0) {
            for (int id : textViewId) {
                hideView(id);
            }
        }
        return this;
    }

    @UiThread
    public BaseViewHolder hideView(@IdRes int textViewId) {
        View view = getItemView(textViewId);
        if (view == null) {
            view = itemView.findViewById(textViewId);
            itemViews.append(textViewId, itemView.findViewById(textViewId));
        }
        if (view != null) {
            view.setVisibility(View.GONE);
            if (view.getParent() instanceof LinearLayout) {
                int index = ((LinearLayout) view.getParent()).indexOfChild(view);
                if (index > 0) {
                    View left = ((LinearLayout) view.getParent()).getChildAt(index - 1);
                    if (TextUtils.equals("line", (String) left.getTag())) {
                        left.setVisibility(View.GONE);
                    }
                }
            }
        }
        return this;
    }

    @UiThread
    public BaseViewHolder setTextColor(int vId, int colorId) {
        TextView tv;
        if (itemViews.indexOfKey(vId) >= 0) {
            tv = (TextView) itemViews.get(vId);
        } else {
            tv = itemView.findViewById(vId);
        }
        if (tv != null) {
            BVH.setColor2View(colorId, tv);
        }
        return this;
    }

    @UiThread
    public BaseViewHolder setTextColor(int colorId) {
        if (textView.size() == 0) if (itemView instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) itemView;
            LinkedList<ViewGroup> queue = new LinkedList<>();
            queue.add(viewGroup);
            while (!queue.isEmpty()) {
                ViewGroup current = queue.removeFirst();
                //dosomething
                for (int i = 0; i < current.getChildCount(); i++) {
                    if (current.getChildAt(i) instanceof ViewGroup) {
                        queue.addLast((ViewGroup) current.getChildAt(i));
                    } else if (current.getChildAt(i) instanceof TextView) {
                        textView.append(textView.size(), (TextView) current.getChildAt(i));
                    }
                }
            }
        }
        if (textView.size() > 0) {
            for (int i = 0; i < textView.size(); i++) {
                BVH.setColor2View(colorId, textView.get(i));
            }
        }
        return this;
    }

    @UiThread
    public BaseViewHolder setItemText(@IdRes int textViewId, Double text) {
        return setItemText(textViewId, String.valueOf(text));
    }

    @UiThread
    public BaseViewHolder setItemText(@IdRes int textViewId, CharSequence text) {
        if (itemView.findViewById(textViewId) instanceof TextView) {
            this.itemViews.append(textViewId, itemView.findViewById(textViewId));
            BVH.setChar2View(text, (TextView) itemView.findViewById(textViewId));
        } else if (this.getItemView(textViewId) instanceof TextView) {
            BVH.setChar2View(text, (TextView) getItemView(textViewId));
            this.itemViews.append(textViewId, getItemView(textViewId));
        } else {
            LOG.d("BaseViewHolder", this.getClass().getSimpleName() + "(" + LOG
                    .useLine() + ").setTextToView(" + text + "," + textViewId + "): textViewId error -> " + textViewId + " is not belongs TextView");
        }
        return this;
    }

    @UiThread
    public BaseViewHolder setItemTextColor(@IdRes int textViewId, int textColor) {
        if (itemView.findViewById(textViewId) instanceof TextView) {
            this.itemViews.append(textViewId, itemView.findViewById(textViewId));
            BVH.setColor2View(textColor, ((TextView) itemView.findViewById(textViewId)));
        } else if (getItemView(textViewId) != null) {
            BVH.setColor2View(textColor, ((TextView) getItemView(textViewId)));
            this.itemViews.append(textViewId, getItemView(textViewId));
        } else {
            LOG.d("BaseViewHolder", this.getClass().getSimpleName() + "(" + LOG
                    .useLine() + ").setTextToView(" + textColor + "," + textViewId + "): textViewId error -> " + textViewId + " is not belongs TextView");
        }
        return this;
    }

    protected String getTextFromView(@IdRes int textViewId) {
        if (itemViews.get(textViewId) != null) {
            return ((TextView) getItemView(textViewId)).getText().toString();
        } else if (itemView.findViewById(textViewId) instanceof TextView) {
            itemViews.append(textViewId, itemView.findViewById(textViewId));
            return ((TextView) itemView.findViewById(textViewId)).getText().toString();
        } else {
            LOG.e("BaseViewHolder", "getTextFromView(" + textViewId + "): textViewId error -> " + textViewId + " is not belongs TextView");
            return "";
        }
    }

    public void setPasser(ActionPasser passer) {
        this.mActionPasser = passer;
    }

    public int getMPosition() {//数据
        try {
            return (int) itemView.getTag(TAG_POSITION);
        } catch (Exception e) {
            return -1;
        }
    }

    protected View.OnClickListener itemClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (BaseViewHolder.this instanceof OnInterceptClick) {
                if (((OnInterceptClick) BaseViewHolder.this).intercept(getData(), v, getMPosition())) {
                    return;
                }
            }
            if (mClick != null) {
                mClick.onItemClick((BaseAdapter) getBindingAdapter(), BaseViewHolder.this, getData(), v, getMPosition());
            }
        }
    };

    private OnClickMaker mClick;

    final void setClickInfo(final OnClickMaker info) {
        if (info.noClick()) {
            return;
        }
        this.mClick = info;
        if (info.clickIds != null && info.clickIds.length > 0) {
            for (int clickId : info.clickIds) {
                if (clickId == 0) {
                    itemView.setOnClickListener(itemClick);
                } else if (getItemView(clickId) != null) {
                    getItemView(clickId).setOnClickListener(itemClick);
                }
            }
        } else {
            itemView.setOnClickListener(itemClick);
        }
    }

    protected View.OnLongClickListener itemLongClick = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {

            if (BaseViewHolder.this instanceof OnInterceptClick) {
                if (((OnInterceptClick) BaseViewHolder.this).intercept(getData(), v, getMPosition())) {
                    return true;
                }
            }
            if (mClick != null) return mPress.pressListener
                    .onLongClick((BaseAdapter) getBindingAdapter(), BaseViewHolder.this, getData(), v, getMPosition());

            return false;
        }
    };
    private OnPressMaker mPress;

    final void setPressInfo(final OnPressMaker info) {
        if (info.pressListener == null) {
            return;
        }
        this.mPress = info;
        if (info.clickIds != null && info.clickIds.length > 0) {
            for (int clickId : info.clickIds) {
                if (clickId == 0) {
                    itemView.setOnLongClickListener(itemLongClick);
                } else if (getItemView(clickId) != null) {
                    getItemView(clickId).setOnLongClickListener(itemLongClick);
                }
            }
        } else if (info.pressListener != null) {
            itemView.setOnLongClickListener(itemLongClick);
        }
    }

    protected Context getContext() {
        return mContext;
    }

    void setContext(Context context) {
        this.mContext = context;
    }

    protected ViewGroup parentView;

    public void setRecyclerView(ViewGroup recyclerView) {
        this.parentView = recyclerView;
    }

    public ViewGroup getParentView() {
        return parentView;
    }

    public Object getPassNullable(int position) {
        if (pass != null && pass.size() > position) {
            return pass.get(position);
        }
        return null;
    }

    SparseArray<Object> pass;

    final void setPass(SparseArray<Object> pass) {
        this.pass = pass;
    }

    public void setPassData(Object... passData) {
        if (passData != null && passData.length > 0) {
            if (pass == null) {
                pass = new SparseArray<>();
            }
            for (int i = 0; i < passData.length; i++) {
                pass.put(i, passData[i]);
            }
        }
    }

    public void setPassData(int key, Object obj) {
        if (obj != null) {
            if (pass == null) {
                pass = new SparseArray<>();
            }
            pass.put(key, obj);
        }
    }

//    BaseAdapter parentAdapter;

//    public BaseAdapter getParentAdapter() {
//        return parentAdapter;
//    }

//    public <VH extends BaseViewHolder, DATA> void setParentAdapter(BaseAdapter<DATA, VH> adapter) {
//        this.parentAdapter = adapter;
//    }

    protected final boolean isHeadPosition(int position) {
        return position < 0 && position > Integer.MIN_VALUE / 2;
    }

    protected final boolean isFootPosition(int position) {
        return position < Integer.MIN_VALUE / 2;
    }

    public final void needSelect(BaseAdapter adapter, int position) {
        if (adapter != null && position >= 0) {
            try {
                itemView.setSelected(adapter.isSelect(position));
            } catch (Exception e) {

            }
        }
    }

    public <T> void fillView(T bean) {
        //    if (bean == null) return;
        //    Class clazz = bean.getClass();
        //    Method methods[] = clazz.getMethods();
        //    for (Method method : methods) {
        //      Annotation[] annotations = method.getAnnotations();
        //      if (annotations.length > 0) {
        //        for (Annotation annotation : annotations) {
        //          if (annotation instanceof FillView) {
        //            OnClick inject = (OnClick) annotation;
        //            int[] value = inject.value();
        //            if (value.length > 0) {
        //              for (int id : value) {
        //                setData2View(id, get(View.OnClickListener.class));
        //              }
        //            }
        //          }
        //        }
        //      }
        //    }
    }
}
